using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace ThisIsTheOnlyChamber
{
    public class TheOnlyChamber : Microsoft.Xna.Framework.Game, ISubscriber
    {
        GraphicsDeviceManager graphics;

        Song BackgroundMusic;

        Menu menu;

        List<Chamber> levels = new List<Chamber>();
        int levelIndex = 0;

        GameState currentState;

        public TheOnlyChamber()
        {
            Content.RootDirectory = "Content";
            graphics = new GraphicsDeviceManager(this);
        }

        private Chamber InitializeLevel(int i)
        {
            Chamber ret;

            switch (i)
            {
                case 0:
                    ret = new ChamberOne(this, "Level 1: Only in the footsteps of God will he proceed.");
                    break;
                case 1:
                    ret = new ChamberFour(this, "Level 2: He mounted the cherubim and flew; he soared on the wings of the wind.");
                    break;
                case 2:
                    ret = new ChamberThree(this, "Level 3: Alcohol makes the drinker unstable.");
                    break;
                case 3:
                    ret = new ChamberFive(this, "Level 4: The stranger did not lodge in the street: But I opened my doors to the traveller.");
                    break;
                case 4:
                    ret = new ChamberTwo(this, "Level 5: Only in the leap from the lion's head will he prove his worth.");
                    break;
                default:
                    ret = new ChamberOne(this, "Level " + (i + 1).ToString() + ": There's a hole in the sky, through which things can fly.");
                    break;
            }

            ret.Subscribe(this);
            return ret;
        }

        private void LoadLevels()
        {
            levels.Clear();
            levels.Add(InitializeLevel(0));
            levels.Add(InitializeLevel(1));
            levels.Add(InitializeLevel(2));
            levels.Add(InitializeLevel(3));
            levels.Add(InitializeLevel(4));
        }

        protected override void Initialize()
        {
            menu = new Menu(this);
            menu.Subscribe(this);

            LoadLevels();

            currentState = menu;

            BackgroundMusic = Content.Load<Song>("ghosts22");
            MediaPlayer.IsRepeating = true;
            MediaPlayer.Play(BackgroundMusic);

            base.Initialize();
        }

        protected override void LoadContent()
        {
            base.LoadContent();

            menu.ReloadContent();

            foreach (Chamber l in levels)
            {
                l.ReloadContent();
            }
        }

        protected override void Update(GameTime gameTime)
        {
            currentState.ProcessGamePad(GamePad.GetState(PlayerIndex.One));
            currentState.ProcessKeyboardMouse(Keyboard.GetState(), Mouse.GetState());
            currentState.Update(gameTime);

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.Black);
            currentState.Draw(gameTime);

            base.Draw(gameTime);
        }

        public void RecieveMessage(Message M)
        {
            switch (M.Kind)
            {
                case (int)Message.Type.StartGame:
                    currentState = levels[0];
                    break;
                case (int)Message.Type.LevelWon:
                    if (levelIndex == levels.Count - 1)
                    {
                        currentState = menu;
                        levelIndex = 0;
                        LoadLevels();
                    }
                    else
                        currentState = levels[++levelIndex];
                    break;
                case (int)Message.Type.LevelLost:
                    levels[levelIndex] = InitializeLevel(levelIndex);
                    currentState = levels[levelIndex];
                    break;
                case (int)Message.Type.Quit:
                    this.Exit();
                    break;
                default:
                    break;
            }
        }
    }
}
